package common

import (
	"bytes"
	"errors"
	"fmt"
	"reflect"
)


var(
	ErrNotFound = errors.New("value Not find in the queue")
)

const MaxQueueLimit = 4096
/*注册一个Queue支持的 support type 列表*/
type MyInt int
func (this  *MyInt )Equal(v interface{}) (bool,error) {
	return *this == v,nil
}



func NewQueue(limit uint64 ,valueType reflect.Kind) *Queue{
	return &Queue{
		queue:make([]interface{},0),
		len:0,
		limit:limit,
		ValueType:valueType,
	}
}


// 实现这个接口的 类型 可以支持 SerchValue 和 DeleteValue
type QueueElemEqual interface {
	Equal(value interface{}) (bool,error)
}
type Queue struct {
	queue []interface{}
	len uint64
	limit uint64
	ValueType reflect.Kind
}



func (this * Queue)CheckQueueLimit( ) error{
	if this.limit < 1 || this.limit>MaxQueueLimit{
		return errors.New("value of queue limit is invalid")
	}
	return nil
}

func (this * Queue)CheckQueueLenForOut(outLen uint64 ) error{
	err := this.CheckQueueLimit()
	if err !=nil{
		return err
	}
	if this.len  > this.limit{
		return errors.New("Queue length exceeds high limit")
	}
	if this.len - 1 < 0 {
		return errors.New("Queue length exceeds lower limit")
	}


	return nil
}

func (this * Queue)CheckQueueLenForJoin(joinLen  uint64 ) error{
	err := this.CheckQueueLimit()
	if err !=nil{
		return err
	}
	if this.len + joinLen > this.limit{
		return errors.New("Queue length exceeds high limit")
	}
	if this.len < 0 {
		return errors.New("Queue length exceeds lower limit")
	}

	return nil
}

func (this * Queue)CheckQueueOutIndex(index uint64  ) error{
	err := this.CheckQueueLimit()
	if err !=nil{
		return err
	}

	if this.len  > this.limit{
		return errors.New("Queue length exceeds high limit")
	}
	if this.len - 1 < 0 {
		return errors.New("Queue length exceeds lower limit")
	}

	if uint64(index) >= this.len || index <0 {
		return errors.New("index beyond the range of queue")
	}
	return nil
}

func (this * Queue)CheckIndex(index uint64  ) error{
	err := this.CheckQueueLimit()
	if err !=nil{
		return err
	}

	if uint64(index) >= this.len || index <0 {
		return errors.New("index beyond the range of queue")
	}
	return nil
}



//从尾加
func (this *Queue)Join(elem interface{} ) error {

	err := this.CheckQueueLenForJoin(1)
	if err != nil {
		return err
	}

	this.queue = append( this.queue , elem)
	this.len ++

	return nil
}
//从头出
func (this * Queue)Out() (interface{},error) {
	err := this.CheckQueueLenForOut(1)
	if err != nil {
		return nil,err
	}
	outToken := this.queue[0]
	this.queue =  this.queue[1:]
	this.len --

	return outToken,nil
}

func (this *Queue)OutIndex(index uint64 ) (interface{},error) {
	err := this.CheckQueueLenForOut(1)
	if err != nil {
		return nil,err
	}
	err = this.CheckIndex(1)
	if err != nil {
		return nil,err
	}
	outToken := this.queue[index]
	this.queue =  append(this.queue[:index] , this.queue[index+1:]...)
	this.len --

	return outToken,nil
}
func (this *Queue)GetByIndex(index uint64 ) (interface{},error) {

	err := this.CheckIndex(index)
	if err != nil {
		return nil,err
	}
	Token := this.queue[index]

	return Token,nil
}
func (this * Queue)Len() uint64 {
	return this.len
}

func (this * Queue)Full() bool {
	return this.len == this.limit
}


func (this * Queue)Empty() bool {
	return this.len == 0 && this.limit > 0
}

// 因为要使用反射 索引传进来的必须是指针
/* 如果error 不为空 则代表出错*/
func (this * Queue)SearchValueForStruct(valuePointer QueueElemEqual) (index uint64 , err error ){
	if t := reflect.TypeOf(valuePointer).Kind() ;t!=reflect.Ptr{
		return 0 ,errors.New("Queue::SearchValueForStruct(elem) import elem must be ptr  ")
	}

	for i ,value := range this.queue {
		index := uint64(i)
		ok,err := valuePointer.Equal(value)
		if ok && err==nil {
			err = this.CheckIndex(index)
			if err != nil {
				return 0,err
			}
			return index,nil
		}else   {
			return 0,err
		}
	}

	return  0,err
}


func (this * Queue)DeleteValueForStruct (value QueueElemEqual) (bool ,error){
	index,err  := this.SearchValueForStruct (value)
	if err != nil{
		return false,err
	}
	this.queue = append(this.queue[:index],this.queue[index+1:]...)
	this.len --
	return true ,nil
}


func (this * Queue)SearchValueForUint64(value uint64) (index uint64,err error ){

	for i,v := range this.queue{
		if vv,ok := v.(uint64) ;ok {
			fmt.Println("正在比较:",vv ,"<==>",value)
			if vv == value{
				fmt.Println("比较成功")
				index := uint64(i)
				return index,nil
			}
		}
	}

	return 0,ErrNotFound
}

func (this * Queue)DeleteValue(value uint64) (error) {
	index ,err := this.SearchValueForUint64(value)
	if err != nil {
		return err
	}

	this.queue = append(this.queue[:index],this.queue[index+1:]...)
	this.len--
	return nil
}

// 因为要使用反射 索引传进来的必须是指针
func (this * Queue)SearchValueForType(valuePointer interface{}) (index uint64,err error ){
	if t := reflect.TypeOf(valuePointer).Kind() ;t!=reflect.Ptr{
		return 0 ,errors.New("Queue::SearchValueForStruct(elem) import elem must be ptr  ")
	}
	value := reflect.ValueOf(valuePointer).Elem()
	if value.Kind() != this.ValueType {
		return 0 ,errors.New("Queue::SearchValueForStruct(elem) import elem type is different with queue value type ")
	}
	valueBytes := value.Bytes()

	for i,v := range this.queue {
		index = uint64(i)
		vBytes := reflect.ValueOf(v).Bytes()
		if  bytes.Equal(valueBytes, vBytes) {
			err = this.CheckIndex(index)
			if err != nil {
				return 0,err
			}
			return index,nil
		}else{
			return 0,err
		}

		//ok := (v == valuePointer) /* 这是错误的  指针对比  后面再修改 */
	}

	return  0,err
}


func (this * Queue)DeleteValueForType(value interface{}) (bool ,error){
	index,err  := this.SearchValueForType(value)
	if err != nil{
		return false,err
	}
	this.queue = append(this.queue[:index],this.queue[index+1:]...)
	this.len--
	return true ,nil
}

